
import tablestore.error
from .column import *
import copy
import json
from typing import Callable, Generic, List, Dict, Tuple, Type, Union, get_args
from typing import TypeVar
from typing import Any

from pydantic import BaseModel
from pydantic._internal._model_construction import ModelMetaclass as ModelMetaclass
import tablestore

from .filter import *
from .client import client
from . import error as Error

_client_key = '_tb_client'

_TSModel = TypeVar("_TSModel", bound="TSModel")

# https://www.liaoxuefeng.com/wiki/1016959663602400/1018490605531840

_T = TypeVar("_T")
def __dataclass_transform__(
    *,
    eq_default: bool = True,
    order_default: bool = False,
    kw_only_default: bool = False,
    field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
) -> Callable[[_T], _T]:
    return lambda a: a

@__dataclass_transform__(kw_only_default=True, field_descriptors=(Column, PrimaryKey, ColumnInfo, PrimaryKeyInfo))
class TSModelMetaClass(ModelMetaclass):
    def __getattr__(cls, name):
        mf = cls.model_fields
        if name in cls.model_fields:
            return cls.model_fields[name]
        else:
            return super().__getattribute__(name)
        
    def __new__(
        cls,
        classname: str,
        bases: Tuple[Type[Any], ...],
        attrs: Dict[str, Any],
        model = False,
        **kwargs: Any,
    ) -> Any:
        
        if not classname=='TSModel':
            __annotations__: Dict = attrs.get('__annotations__', {})
            for k, v in attrs.items():
                if isinstance(v, PrimaryKeyInfo):
                    if v.autoincrement:
                        __annotations__[k] = Optional[int]
        new_cls = super().__new__(cls, classname, bases, attrs, **kwargs)
        

        if not classname=='TSModel':

            # 保存列和主键；主键子类包含父类，父类不包含子类；列不共享
            new_cls.__columns__ = [] # : List[str]
            new_cls.__primaryKeys__ = [] #: List[str] 所有的主键（按声明时指定的顺序插入，第一位的是mainPK）
            new_cls.__secondaryIndexKeyMap__ = {}  # Dict[str, List[str]] key为各个主键，value为将该主键作为二级索引的mainPK重新排列后的主键顺序（重排方式为将目标主键从__primaryKeys__中提到第一位作为mainPK） 
            if hasattr(new_cls.__base__, '__primaryKeys__'):
                super_pk = copy.deepcopy(new_cls.__base__.__primaryKeys__)
                super_secIndex = copy.deepcopy(new_cls.__base__.__secondaryIndexKeyMap__)
                new_cls.__primaryKeys__.extend(super_pk)
                new_cls.__secondaryIndexKeyMap__.update(super_secIndex)
            
            # 查找表名
            table_name = attrs.get('__table__', '')
            if not table_name:
                table_name = attrs.get('__tablename__', '')
            if not table_name:
                found = False
                for base in bases:
                    if hasattr(base, '__table__'):
                        table_name = base.__table__
                        found = True
                        break
                    elif hasattr(base, '__tablename__'):
                        table_name = base.__tablename__
                        found = True
                        break
                if not found and model == True:
                    raise TypeError("<%s> does not have a __table__ or __tablename__" % (classname))
            new_cls.__table__ = table_name

            # 初始化属性
            for k, v in attrs.items():
                if isinstance(v, ColumnInfo): #  and not hasattr(new_cls, k)
                    v.name = k
                    new_cls.model_fields[k].name = k
                    if isinstance(v, PrimaryKeyInfo):
                        if v.index >= 3: # 表存储最多只能4个主键
                            raise ValueError(f'表存储最多只能4个主键, pk_name = {k}')
                        if k not in new_cls.__primaryKeys__:
                            new_cls.__primaryKeys__.insert(v.index, k)
                        if v.index == 0 and not v.sec_index_tb_name:
                            v.sec_index_tb_name = new_cls.__table__
                    else:
                        if k not in new_cls.__columns__:
                            new_cls.__columns__.append(k)
                # setattr(new_cls, k, v)
                
            for index in range(1, len(new_cls.__primaryKeys__)):
                copy_keys = copy.copy(new_cls.__primaryKeys__)
                pk = copy_keys.pop(index)
                copy_keys.insert(0, pk)
                new_cls.__secondaryIndexKeyMap__[pk] = copy_keys
                    
            if new_cls.__primaryKeys__:
                new_cls.__secondaryIndexKeyMap__[new_cls.__primaryKeys__[0]] = new_cls.__primaryKeys__
        
        
        return new_cls
        

    def __init__(cls, classname: str, bases: Tuple[type, ...], attrs: Dict[str, Any], **kw: Any)->None:

        ModelMetaclass.__init__(cls, classname, bases, attrs, **kw)

def model_init(*, self: "TSModel", data: Dict[str, Any]) -> None:
        old_dict = self.__dict__.copy()
        self.__pydantic_validator__.validate_python(
                data,
                self_instance=self,
            )
        object.__setattr__(
            self,
            "__dict__",
            {**old_dict, **self.__dict__},
        )

class TSModel(BaseModel, metaclass=TSModelMetaClass):
    # __columns__ : List[str] = [] 
    # __primaryKeys__ : List[str]  = [] #所有的主键（按声明时指定的顺序插入，第一位的是mainPK）
    # __secondaryIndexKeyMap__ : Dict[str, List[str]]= {}  #  key为各个主键，value为将该主键作为二级索引的mainPK重新排列后的主键顺序（重排方式为将目标主键从__primaryKeys__中提到第一位作为mainPK）
    # __table__: str

    def __init__(__self__, **data: Any) -> None:
        cls_ = type(__self__)
        model_init(self=__self__, data=data)

    @classmethod
    def _get_column_type(cls, column: ColumnInfo) -> Any:
        _attributes_set = column._attributes_set
        annotation = _attributes_set.get('annotation', None)
        if get_args(annotation):
            annotation = get_args(annotation)[0]
        return annotation
    
    # @classmethod
    # def __getattr__(self, key):
    #     return self.__dict__.get(key, None)

    def __setattr__(self, key, value):
        _value = value
        if key in self.model_fields:
            field_info = self.model_fields[key]
            if isinstance(field_info, ColumnInfo) and field_info.json_obj:
                annotation = TSModel._get_column_type(field_info)
                if annotation == List or annotation == Dict:
                    _value = json.loads(value)
                try:
                    if issubclass(annotation, BaseModel):
                        _value = annotation.model_validate_json(value)
                except TypeError as e:
                    pass

        super().__setattr__(key, _value)

    @classmethod
    def _get_pk_name_list(cls: Type[_TSModel], main_pk: ColumnInfo = None) -> List[str]:
        """获取主键名列表

        Args:
            main_pk_name (str, optional): 首个主键名，其余按照原主键顺序排列。当main pk是column时，如果是全局索引，则将main pk放在首位，否则放在第二位，主键数有可能超出4个。

        Returns:
            List[str]: 主键列表
        """ 
        if main_pk != None:
            if isinstance(main_pk, PrimaryKeyInfo):
                pk_name_list = cls.__secondaryIndexKeyMap__[main_pk.name]
            else:
                pk_name_list = copy.deepcopy(cls.__primaryKeys__)
                if main_pk.sec_index_type == tablestore.SecondaryIndexType.GLOBAL_INDEX:
                    pk_name_list.insert(0, main_pk.name)
                else:
                    pk_name_list.insert(1, main_pk.name)
        else:
            pk_name_list = cls.__primaryKeys__
        return copy.deepcopy(pk_name_list)
    
       
    @classmethod
    def _get_column_name_list(cls: Type[_TSModel], include_base = False) -> List[str]:
        """获取所有预定义列名

        Args:
            include_base (bool, optional): 是否包含父类的列. True返回所有父类的列，False只返回当前类的列

        Returns:
            List[str]: 预定义列名列表
        """
        if not include_base:
            return copy.deepcopy(cls.__columns__)
        else:
            columns = []
            for k, v in cls.model_fields.items():
                if isinstance(v, ColumnInfo) and not isinstance(v, PrimaryKeyInfo):
                    columns.append(k)
            return columns
        
    @classmethod
    def _get_pk_list(cls: Type[_TSModel], main_pk: PrimaryKeyInfo = None) -> List[PrimaryKeyInfo]:
        """获取所有的PrimaryKeyInfo

        Args:
            cls (Type[_TSModel]): _description_
            main_pk (PrimaryKeyInfo, optional): 以哪个pk作为首个pk. Defaults to None.

        Returns:
            List[PrimaryKeyInfo]
        """
        name_list = cls._get_pk_name_list(main_pk=main_pk)
        pk_list = []
        for name in name_list:
            pk_list.append(cls.model_fields[name])
        return pk_list
    
    @classmethod
    def _get_column_list(cls: Type[_TSModel], include_base = False) -> List[ColumnInfo]:
        c_list = []
        name_list = cls._get_column_name_list(include_base=include_base)
        for name in name_list:
            c_list.append(cls.model_fields[name])
        return c_list


    def _get_value_from_default_factory(self, c_name: str, b_create: bool) -> Optional[Tuple[str, Any]]:
        """通过default_factory创建列的值

        Args:
            c_name (str): 列名
            b_create (bool): 获取的目的是创建行数据还是更新行数据

        Returns:
            (c_name, value), 返回None表示不需要更新
        """
        column = self.model_fields.get(c_name, None)
        if column == None:
            return None
        value = None
        if column.default_factory == default_created_ms:
            value = default_created_ms(b_create=b_create)
        elif column.default_factory == default_updated_ms:
            value = default_updated_ms()
        else:
            raise ValueError("default_factory不存在或不属于指定factory")
        if value == None:
            return None
        return (c_name, value)
        

    def _get_pk_value_list(self, b_create: bool, main_pk: PrimaryKeyInfo = None, default=tablestore.INF_MIN) -> List[Tuple[str, Any]]:
        """返回所有pk的kv列表，顺序以main_pk_name为第一个，其余按照主键顺序排列

        Args:
            main_pk_name (str, optional): _description_. Defaults to ''.
            default (_type_, optional): 如果值为空时使用的默认值. Defaults to tablestore.INF_MIN.

        Returns:
            List: [(main_pk_name, value),(key_name, value),(key_name, value)]
        """
        pk_name_list = self.__class__._get_pk_name_list(main_pk=main_pk)
        pk_values = []
        for key in pk_name_list:
            try:
                value_from_def = self._get_value_from_default_factory(key, b_create=b_create)
                if value_from_def != None:
                    pk_values.append(value_from_def)
                continue
            except:
                pass
            value = getattr(self, key, None)
            if value == None:
                if self.__class__.model_fields[key].autoincrement:
                    value = tablestore.PK_AUTO_INCR
                else:
                    value = default
            elif issubclass(type(value), enum.Enum):
                value = value.value

            pk_values.append( (key, value ) )
        return pk_values
    
    def _get_column_value_list(self, b_create: bool) -> List[Tuple[str, Any]]:
        """获取所有预定义列的值，用于更新表

        Returns:
            List[Tuple[str, Any]]: [(预定义名称， 预定义值),...]
        """
        attribute_columns = []
        for key in self.__class__._get_column_name_list(include_base=True):
            try:
                value_from_def = self._get_value_from_default_factory(key, b_create=b_create)
                if value_from_def != None:
                    attribute_columns.append(value_from_def)
                continue
            except:
                pass
            value = getattr(self, key, None)
            if isinstance(value, list) or isinstance(value, dict):
                value = json.dumps(value, ensure_ascii=False).encode('utf8')
            elif issubclass(type(value), enum.Enum):
                value = value.value
            try:
                if issubclass(value, BaseModel):
                    value = value.model_dump_json()
            except TypeError as e:
                pass
            attribute_columns.append((key, value))
        return attribute_columns

    # 插入或覆盖更新数据
    @client
    def save(self, return_type = tablestore.ReturnType.RT_PK, **kwargs):
        """插入或覆盖更新数据

        Args:
            return_type (_type_, optional): 返回完整主键结果. Defaults to tablestore.ReturnType.RT_PK.

        Raises:
            ValueError: 未初始化

        Returns:
            _type_: _description_
        """
        client: tablestore.OTSClient = kwargs.get(_client_key)
        if not client:
            raise ValueError('not client')
        primary_kv_list = self._get_pk_value_list(b_create=True)

        attribute_columns = self._get_column_value_list(b_create=True)
        
        row = tablestore.Row(primary_kv_list, attribute_columns)
        consumed, return_row = client.put_row(self.__class__.__table__, row, return_type = return_type)
        primary_kv_res = return_row.primary_key
        for k, v in primary_kv_res:
            if hasattr(self, k):
                setattr(self, k, v)
        return consumed, return_row

    @client
    def update_not_empty(self, **kwargs):
        """更新一行数据

        Raises:
            ValueError: 未初始化

        Returns:
            _type_: _description_
        """
        client: tablestore.OTSClient = kwargs.get(_client_key)
        if not client:
            raise ValueError('not client')
        primary_kv_list = self._get_pk_value_list(b_create=False)

        attribute_columns = self._get_column_value_list(b_create=False)

        update_of_attribute_columns = {
            'PUT' : attribute_columns
        }
        row = tablestore.Row(primary_kv_list, update_of_attribute_columns)
        condition = tablestore.Condition('EXPECT_EXIST')
        consumed, return_row = client.update_row(self.__class__.__table__, row, condition)
        return consumed, return_row

    @classmethod
    def _create_secondary_index_meta(cls: Type[_TSModel], main_pk: ColumnInfo, other_pk: List[ColumnInfo]=[]) -> tablestore.SecondaryIndexMeta:
        """创建二级索引建表信息

        Args:
            main_pk (ColumnInfo): 作为main pk的列。当column不是主键时，如果是全局索引，则将column放在首位，否则放在第二位。主键数有可能超出4个，超出的会被放在列的最前面。

        Raises:
            ValueError: 列需要有sec_index_tb_name

        Returns:
            tablestore.SecondaryIndexMeta
        """
        if not main_pk.sec_index_tb_name:
            raise ValueError('sec_index_tb_name 为空')
        
        c_name_list = cls._get_column_name_list(include_base=True)
        
        if isinstance(main_pk, PrimaryKeyInfo):
            primary_key_names = cls._get_pk_name_list(main_pk=main_pk)
            sec_meta = tablestore.SecondaryIndexMeta(main_pk.sec_index_tb_name, primary_key_names, c_name_list,
                                                        index_type=main_pk.sec_index_type)
        else:
            pk_name_list_4_sec = cls._get_pk_name_list(main_pk=main_pk)
            c_name_list.remove(main_pk.name)
            if len(pk_name_list_4_sec) > 4:
                last_pk_name = pk_name_list_4_sec.pop()
                c_name_list.insert(0, last_pk_name)
            sec_meta = tablestore.SecondaryIndexMeta(main_pk.sec_index_tb_name, pk_name_list_4_sec, c_name_list,
                                                        index_type=main_pk.sec_index_type)
        return sec_meta
    
    @classmethod
    @client
    def create_table(cls: Type[_TSModel], _tb_client: tablestore.OTSClient = ...,
                     time_to_live=-1, max_version=1, max_time_deviation=86400, allow_update=True)->bool:
        """创建表

        Args:
            time_to_live (int, optional): 数据的过期时间，至少为86400秒（一天）或-1（数据永不过期）. Defaults to -1.
            max_version (int, optional): 属性列能够保留数据的最大版本个数。当属性列数据的版本个数超过设置的最大版本数时，系统会自动删除较早版本的数据. Defaults to 1.
            max_time_deviation (int, optional): 写入数据的时间戳与系统当前时间的偏差允许最大值. Defaults to 86400.
            allow_update (_type_, optional): 是否允许UpdateRow相关更新写入操作，多元索引生命周期功能必须为False. Defaults to True.

        Raises:
            ValueError: 主键或者预定义列的类型错误

        Returns:
            bool: True 创建成功，False 表已存在
        """
        # 主键列
        schema_of_primary_key = []
        pk_list = cls._get_pk_list()
        for pk in pk_list:
            annotation = TSModel._get_column_type(pk)
            type_T = ()
            if  issubclass(annotation, str):
                type_T = (pk.name, 'STRING')
            elif issubclass(annotation, int) or issubclass(annotation, enum.Enum):
                if pk.autoincrement: 
                    type_T = (pk.name, 'INTEGER', tablestore.PK_AUTO_INCR)
                else:
                    type_T = (pk.name, 'INTEGER')
                
            else:
                raise ValueError("主键类型错误，必须是str或者int")
            schema_of_primary_key.append(type_T)

        # 配置数据表的预定义列
        defined_columns = []
        column_list = cls._get_column_list(include_base=True)
        for column in column_list:
            annotation = annotation = TSModel._get_column_type(column)
            if  issubclass(annotation, str):
                defined_columns.append((column.name, 'STRING'))
            elif issubclass(annotation, bool):
                defined_columns.append((column.name, 'BOOLEAN'))
            elif issubclass(annotation, int) or issubclass(annotation, enum.Enum):
                defined_columns.append((column.name, 'INTEGER'))
            elif issubclass(annotation, float):
                defined_columns.append((column.name, 'DOUBLE'))
            
            else:
                raise ValueError("预定义列类型错误，必须是str/int/double/bool")
            
        # 通过数据表名称和主键列的schema创建一个tableMeta。
        table_meta = tablestore.TableMeta(cls.__table__, schema_of_primary_key, defined_columns)
        # 创建TableOptions，数据永不过期，只保存1个版本数据。
        table_option = tablestore.TableOptions(time_to_live=time_to_live, max_version=max_version, max_time_deviation=max_time_deviation, allow_update=allow_update)
        # 设置预留读吞吐量为0，预留写吞吐量为0。
        reserved_throughput = tablestore.ReservedThroughput(tablestore.CapacityUnit(0, 0))
        # 设置二级索引的索引名称、主键列和属性列。索引类型默认为全局二级索引。
        secondary_indexes = []
        for pk in pk_list:
            if pk.sec_index_tb_name:
                sec_meta = cls._create_secondary_index_meta(main_pk=pk)
                secondary_indexes.append(sec_meta)
        for c in column_list:
            if c.sec_index_tb_name:
                sec_meta = cls._create_secondary_index_meta(main_pk=c)
                secondary_indexes.append(sec_meta)

        # 调用client的create_table接口，如果没有抛出异常，则说明执行成功。
        try:
            _tb_client.create_table(table_meta, table_option, reserved_throughput, secondary_indexes)
        except tablestore.error.OTSServiceError as e:
            if e.code == 'OTSObjectAlreadyExist':
                return False
            raise e
        return True

    @classmethod
    @client
    def delete_table(cls: Type[_TSModel], _tb_client: tablestore.OTSClient = ...):
        try:
            _tb_client.delete_table(cls.__table__)
        except tablestore.error.OTSServiceError as e:
            if e.code == 'OTSObjectAlreadyExist':
                return False
            raise e
        return True

    @classmethod
    @client
    def create_secondary_index(cls: Type[_TSModel], column: ColumnInfo, include_base_data = True, _tb_client: tablestore.OTSClient = ...)-> bool:
        """创建二级索引表

        Args:
            column (ColumnInfo): 指定创建二级索引的列
            include_base_data (bool, optional): 是否索引表是否包含已有的数据. Defaults to True.

        Raises:
            e: tablestore.error.OTSServiceError

        Returns:
            bool: False 已存在同名索引表
        """
        sec_meta = cls._create_secondary_index_meta(main_pk=column)
        try:
            _tb_client.create_secondary_index(cls.__table__, sec_meta, include_base_data)
        except tablestore.error.OTSServiceError as e:
            if e.code == 'OTSObjectAlreadyExist':
                return False
            raise e
        return True

    @classmethod
    @client
    def create_search_index(cls: Type[_TSModel], routing_pk: List[PrimaryKeyInfo]=[], _tb_client: tablestore.OTSClient = ...) -> bool:
        ## 文档： https://help.aliyun.com/zh/tablestore/developer-reference/create-search-indexes-by-using-python-sdk?spm=a2c4g.11186623.0.0.5fd2691940Yc2o
        """创建多元索引表。如果culumn没设置extra_search_scheme，则会创建一个默认的SearchFieldSchema。自动使用column的name，并识别基础类型

        Args:
            cls (Type[_TSModel]): _description_
            search_index_name (str): _description_
            routing_pk (List[PrimaryKeyInfo], optional): 用于分区的路由主键. Defaults to [].
            _tb_client (tablestore.OTSClient, optional): _description_. Defaults to ....
        Returns:
            bool: False 已存在同名索引表
        """
        pk_list = cls._get_pk_list()
        column_list = cls._get_column_list(include_base=True)
        all_column = pk_list + column_list

        fields = []
        for column in all_column:
            field = column.extra_search_scheme
            if field == None:
                field = SearchFieldSchema(field_name=column.name)
            if not field.field_name:
                field.field_name = column.name
            if field.field_type == None:
                f_type = None
                ann = TSModel._get_column_type(column)
                if issubclass(ann, str): # ann == str:
                    f_type = tablestore.FieldType.KEYWORD
                elif issubclass(ann, bool):
                    f_type = tablestore.FieldType.BOOLEAN
                elif issubclass(ann, int) or issubclass(ann, enum.Enum):
                    f_type = tablestore.FieldType.LONG
                elif issubclass(ann, float):
                    f_type = tablestore.FieldType.DOUBLE    
                
                field.field_type = f_type
            fields.append(field)
        
        routing_fields = []
        for pk in routing_pk:
            routing_fields.append(pk.name)
        index_setting = tablestore.IndexSetting(routing_fields=routing_fields) 
        #index_sort = None #当多元索引中存在Nested类型字段时，不能设置索引预排序.
        index_sort = tablestore.Sort(sorters=[tablestore.PrimaryKeySort(tablestore.SortOrder.ASC)])
        index_meta = tablestore.SearchIndexMeta(fields, index_setting=index_setting, index_sort=index_sort)

        try:
            _tb_client.create_search_index(cls.__table__, cls.__table__, index_meta)
        except tablestore.error.OTSServiceError as e:
            if e.code == 'OTSObjectAlreadyExist':
                return False
            raise e
        return True

    @classmethod
    @client
    def find_by_pk(cls: Type[_TSModel], pk_values: List[Union[str, int, float]], client: tablestore.OTSClient = ...) -> _TSModel:
        """使用完整的主键查询一条数据

        Args:
            pk_values (List): 完整的主键的值，按表的主键顺序排列

        Raises:
            ValueError: 没有client或者主键值数量不对应主键数量

        Returns:
            Self@BaseMode: model
        """
        pk_list = cls._get_pk_name_list()

        if len(pk_list) != len(pk_values):
            raise ValueError('pk_values length not equal pk nums')
        
        primary_kv = []
        for index, k  in enumerate(pk_list):
            primary_kv.append( (k, pk_values[index]) )

        _, row, _ = client.get_row(cls.__table__, primary_kv)
        if not row:
            return None
        
        params = {}
        for column_name, value in row.primary_key:
            params[column_name] = value
        for column_name, value, _ in row.attribute_columns:
            params[column_name] = value

        model = cls(**params)
        return model
    
    @classmethod
    @client
    def delete_by_pk(cls: Type[_TSModel], pk_values: List[Union[str, int, float]], _tb_client: tablestore.OTSClient = ...):
        pk_list = cls._get_pk_name_list()

        if len(pk_list) != len(pk_values):
            raise ValueError('pk_values length not equal pk nums')
        
        primary_kv = []
        for index, k  in enumerate(pk_list):
            primary_kv.append( (k, pk_values[index]))
        row = tablestore.Row(primary_kv)
        consumed, return_row = _tb_client.delete_row(cls.__table__, row, None)

    # 范围查找，当前一个PK为范围而不是具体某个值时，后面的PK无效
    @classmethod
    @client
    def query_by_pk(cls: Type[_TSModel], pk_filters: List[Filter], column_filters: List[Filter]=[], limit: int = None, **kwargs) -> List[_TSModel]:
        """范围查找，当前一个PK为范围而不是具体某个值时，后面的PK无效

        Args:
            pk_filters (List[Filter]): 按表已定义顺序的主键筛选器。第0个主键会被作为查询的第一列主键，并使用sec_index_tb_name作为表名
            column_filters (List[Filter], optional): 列筛选器. Defaults to [].
            limit (_type_, optional): 最大行数. Defaults to None.

        Raises:
            ValueError: 表存储未初始化
            Error.EmptySceIndexTBName: pk_filters[0]需要设置sec_index_tb_name
            Error.NotPrimaryKeyError: pk_filters需要都是主键类型

        Returns:
            _type_: _description_
        """
        client: tablestore.OTSClient = kwargs.get(_client_key)
        if not client:
            raise ValueError('not client')

        start_primary_key = []
        end_primary_key = []

        pk_name_list = []
        main_pk: PrimaryKeyInfo = pk_filters[0].column
        if not main_pk.sec_index_tb_name:
            raise Error.EmptySceIndexTBName()
        
        if pk_filters[0].is_pk():   
            pk_name_list = cls._get_pk_name_list(main_pk=main_pk)
        else:
            raise Error.NotPrimaryKeyError()
        
        for pk_name in pk_name_list:
            for filter in pk_filters:
                if filter.column.name == pk_name:
                    start_primary_key.append(filter.operators[0])
                    end_primary_key.append(filter.operators[1])
                    break
                else:
                    start_primary_key.append((pk_name, tablestore.INF_MIN))
                    end_primary_key.append((pk_name, tablestore.INF_MAX))

        column_filter  = None
        conditions = []
        for c_filter in column_filters:
            if c_filter.operator_type != OperatorType.IN:
                conditions.extend(c_filter.operators)

        if len(conditions) == 1:
            column_filter = conditions[0]
        elif len(conditions) > 1:
            column_filter = tablestore.CompositeColumnCondition(tablestore.LogicalOperator.AND)
            for condition in conditions:
                column_filter.add_sub_condition(condition)
        
        c_name_list = cls._get_column_name_list(include_base=True)

        consumed, next_start_primary_key, rows, next_token = client.get_range(
            main_pk.sec_index_tb_name, tablestore.Direction.FORWARD, start_primary_key, end_primary_key, columns_to_get=c_name_list, limit=limit, column_filter=column_filter)

        all_rows = []
        all_rows.extend(rows)

        while next_start_primary_key is not None:
            consumed, next_start_primary_key, rows, next_token = client.get_range(
            main_pk.sec_index_tb_name, tablestore.Direction.FORWARD, next_start_primary_key, end_primary_key, columns_to_get=c_name_list, limit=limit, column_filter=column_filter)
            all_rows.extend(rows)

        results = []
        for row in all_rows:
                result = {col[0]: col[1] for col in row.attribute_columns}
                result.update({col[0]: col[1] for col in row.primary_key})
                # result['aid'], result['id'], result['image_id'] = [col[1] for col in row.primary_key]

                model = cls(**result)
                # for attr, value in result.items():
                #     setattr(model, attr, value)
                results.append(model)

        return results

    
    @classmethod
    @client
    def search(cls: Type[_TSModel], filter_list: List[Filter], limit: int=100, offset: int = 0, get_total_count=False, _tb_client: tablestore.OTSClient = ...) -> Tuple[List[_TSModel], tablestore.SearchResponse]:
        must_queries = []
        must_not_queries = []
        for filter in filter_list:
            if filter.operator_type == OperatorType.EQUAL:
                q = tablestore.TermQuery(filter.column.name, filter.value)
                must_queries.append(q)
            elif filter.operator_type == OperatorType.NOT_EQUAL:
                q = tablestore.TermQuery(filter.column.name, filter.value)
                must_not_queries.append(q)
            elif filter.operator_type == OperatorType.IN:
                q = tablestore.TermsQuery(filter.column.name, filter.value)
                must_queries.append(q)
            elif filter.operator_type == OperatorType.BETWEEN:
                q = tablestore.RangeQuery(filter.column.name, filter.value[0], filter.value[1], include_lower=False, include_upper=False)
                must_queries.append(q)
            elif filter.operator_type == OperatorType.LARGER:
                q = tablestore.RangeQuery(filter.column.name, range_from=filter.value[0], include_lower=False, include_upper=False)
                must_queries.append(q)
            elif filter.operator_type == OperatorType.LARGER:
                q = tablestore.RangeQuery(filter.column.name, range_to=filter.value[0], include_lower=False, include_upper=False)
                must_queries.append(q)

        bool_query = tablestore.BoolQuery(must_queries=must_queries, must_not_queries=must_not_queries)
        search_response: tablestore.SearchResponse = _tb_client.search(
        cls.__table__, cls.__table__,
       tablestore.SearchQuery(
            bool_query,
            # sort=Sort(sorters=[FieldSort('Col_Long', SortOrder.ASC)]),
            limit=100,
            offset=offset,
            get_total_count=get_total_count),
            tablestore.ColumnsToGet(return_type=tablestore.ColumnReturnType.ALL)
        )

        all_rows = search_response.rows
        results = []
        for row in all_rows:
                result = {col[0]: col[1] for col in row[0]}
                result.update({col[0]: col[1] for col in row[1]})
                model = cls(**result)
                results.append(model)

        return (results, search_response)
